package com.jiamingZhao.utils;

import com.google.common.collect.Lists;
import com.jiamingZhao.cache.CacheMap;
import com.jiamingZhao.config.DataSourceConfig;
import com.jiamingZhao.enums.FiledType;
import com.jiamingZhao.mapper.base.MPBaseMapper;
import com.jiamingZhao.wrapper.SqlPara;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;

/**
 * @author ：JiaMing Zhao
 * @since ：2025/6/9 16:29
 */
@Slf4j
public final class DbUtil {

    private DbUtil(){

    }


    public static <T> List<T> find(SqlPara<T> sqlPara) {

        return find(sqlPara.getEntityClass(), sqlPara.getSql(), sqlPara.getPara());
    }

    public static  <T> List<T> find(Class<T> entityClass, String sql, Object... paras) {
        Connection conn = DataSourceConfig.getConnection();
        try (PreparedStatement pst = conn.prepareStatement(sql)) {
            fillStatement(pst, paras);
            System.err.println("执行SQL：" + sql);
            ResultSet rs = pst.executeQuery();
            List<T> result = handleResultSet(entityClass, rs);
            close(rs);
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T findFirst(SqlPara<T> sqlPara) {
        List<T> list = find(sqlPara);
        return list.size() == 1 ? list.get(0) : null;
    }

    public static <T> Long count(SqlPara<T> sqlPara) {
        Connection conn = DataSourceConfig.getConnection();
        long num = 0L;
        try (PreparedStatement pst = conn.prepareStatement(sqlPara.getSql())) {
            fillStatement(pst, sqlPara.getPara());
            System.err.println("执行SQL：" + sqlPara.getSql());
            ResultSet rs = pst.executeQuery();
            rs.next();
            num =  rs.getLong("num");
            close(rs);
            return num;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static <T> List<T> handleResultSet(Class<T> entityClass, ResultSet rs) throws Exception {
        List<T> list = Lists.newArrayList();
        while (rs.next()) {
            T entity = entityClass.getDeclaredConstructor().newInstance();
            FiledType.fillEntityFiled(entity, CacheMap.getEntityMethods(entityClass), rs);
            list.add(entity);
        }
        return list;
    }

    public static Class<?> getMapperEntityType(Class<?> mapperClass) {
        // 获取 MPBaseMapper 的泛型参数
        Type[] genericInterfaces = mapperClass.getGenericInterfaces();
        for (Type type : genericInterfaces) {
            if (type instanceof ParameterizedType parameterizedType) {
                if (parameterizedType.getRawType().equals(MPBaseMapper.class)) {
                    // 获取 MPBaseMapper<T> 的 T 类型
                    Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                    if (actualTypeArguments.length > 0) {
                        Type entityType = actualTypeArguments[0];
                        if (entityType instanceof Class) {
                            return (Class<?>) entityType;
                        } else if (entityType instanceof ParameterizedType) {
                            return (Class<?>) ((ParameterizedType) entityType).getRawType();
                        }
                    }
                }
            }
        }
        throw new IllegalArgumentException("无法解析 " + mapperClass.getName() + " 的泛型类型");
    }


    private static void fillStatement(PreparedStatement pst, Object[] paras) throws SQLException {
        for (int i=0; i<paras.length; i++) {
            pst.setObject(i + 1, paras[i]);
        }
    }

    private static void close(ResultSet rs) throws SQLException {
        if (rs != null) {rs.close();}
    }



}
